#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <cstdarg>
#include <ctime>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace std;

enum
{
    Debug = 0,
    Info,
    Warnning,
    Error,
    Fatel
};

enum
{
    Screen = 0,//显示器
    OneFile, //一个文件
    ClassFile //多个文件
};

const int defalut_style = Screen;
const string defalut_filename = "Log.";
const string Logdir = "Log";

string LevelToString(int level)
{
    switch(level)
    {
        case Debug:
            return "Debug";
            break;
        case Info:
            return "Info";           
            break;
        case Warnning:
            return "Warnning";
            break;
        case Error:
            return "Error";
            break;
        case Fatel:
            return "Fatel";
            break;
        defalut:
            return "unknow";
            break;
    }
}

class Log
{
public:
    Log()
     :_style(defalut_style)
     ,_filename(defalut_filename)
    {
        mkdir(Logdir.c_str(), 0775);
    }

    void Eable(int sty)//以什么形式进行读取日志信息
    {
        _style = sty;
    }

    string TimeStampExLocalTime()
    {
        time_t currtime = time(nullptr);
        struct tm* curr = localtime(&currtime);
        char buff_time[128];
        snprintf(buff_time, sizeof(buff_time), "%d-%d-%d %d:%d:%d", curr->tm_yday + 1900, curr->tm_mon + 1, curr->tm_mday, 
                curr->tm_hour, curr->tm_min, curr->tm_sec);
        return buff_time;
    }

    void WriteToOneFile(const string& Logname, const string& messages)
    {
        umask(0);
        int n = open(Logname.c_str(), O_CREAT| O_WRONLY | O_APPEND, 0666);
        if(n < 0)
          return;
        write(n, messages.c_str(), sizeof(messages));
        close(n);
    }

    void WriteClassFile(const string& Levelstyle, const string& messages)
    {
        string Logname = Logdir;
        Logname += "/";
        Logname += _filename;
        Logname += Levelstyle;

        WriteToOneFile(Logname, messages);
    }

    void WriteLog(const string& Levelstr, const string& messages)
    {
        switch(_style)
        {
          case Screen:
            cout << messages << endl;
            break;
          case OneFile:
            WriteToOneFile(Levelstr, messages);
            break;
          case ClassFile:
            WriteClassFile("all", messages);
            break;
          defalut:
            break;
        }
    }

    void LogMessages(int level, const char* format,...)
    {
        char leftbuffer[128];
        string Levelstr = LevelToString(level);
        string CurrTimestr = TimeStampExLocalTime();
        string idstr = to_string(getpid());
        char rightbuffer[1024];

        va_list args; // char *, void *
        va_start(args, format);
        // args 指向了可变参数部分
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, args);
        va_end(args); // args = nullptr;
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%s][%s] ",
                 Levelstr.c_str(), CurrTimestr.c_str(), idstr.c_str());

        std::string loginfo = leftbuffer;
        loginfo += rightbuffer;
        WriteLog(Levelstr, loginfo);
    }

    ~Log()
    {}
private: 
    int _style;
    string _filename;
};

Log log;

class conf
{
public:
    conf()
    {
        log.Eable(Screen);
    }
    ~conf()
    {}
};

conf con;